home *** CD-ROM | disk | FTP | other *** search
/ ADA Programming Guide / ADA Programming Guide.iso / ada_gnu / adainc / a-ngcefu.adb < prev    next >
Text File  |  1996-01-30  |  18KB  |  669 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT RUNTIME COMPONENTS                          --
  4. --                                                                          --
  5. --                     A D A . N U M E R I C S . G C E F                    --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.2 $                              --
  10. --                                                                          --
  11. --           Copyright (c) 1992,1993,1994 NYU, All Rights Reserved          --
  12. --                                                                          --
  13. -- The GNAT library is free software; you can redistribute it and/or modify --
  14. -- it under terms of the GNU Library General Public License as published by --
  15. -- the Free Software  Foundation; either version 2, or (at your option) any --
  16. -- later version.  The GNAT library is distributed in the hope that it will --
  17. -- be useful, but WITHOUT ANY WARRANTY;  without even  the implied warranty --
  18. -- of MERCHANTABILITY  or  FITNESS FOR  A PARTICULAR PURPOSE.  See the  GNU --
  19. -- Library  General  Public  License for  more  details.  You  should  have --
  20. -- received  a copy of the GNU  Library  General Public License  along with --
  21. -- the GNAT library;  see the file  COPYING.LIB.  If not, write to the Free --
  22. -- Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.        --
  23. --                                                                          --
  24. ------------------------------------------------------------------------------
  25.  
  26. --  This is an early trial implementation, simplified for early gnat.
  27. --  It is not a "strict" implementation.
  28. --  All Ada required exception handling is provided.
  29. --  Many special cases are handled locally to avoid unnecessary calls
  30.  
  31. with Ada.Numerics.Generic_Elementary_Functions;
  32.  
  33. package body Ada.Numerics.Generic_Complex_Elementary_Functions is
  34.  
  35.    package Elementary_Functions is new
  36.       Ada.Numerics.Generic_Elementary_Functions (Real'Base);
  37.    use Elementary_Functions;
  38.  
  39.    PI : constant := 3.14159_26535_89793_23846_26433_83279_50288_41971;
  40.    PI_2 : constant := PI / 2.0;
  41.    Log_Two : constant := 0.69314_71805_59945_30941_72321_21458_17656_80755;
  42.  
  43.    Epsilon : Real'Base;
  44.    Square_Root_Epsilon     : Real'Base;
  45.    Inv_Square_Root_Epsilon : Real'Base;
  46.    Root_Root_Epsilon       : Real'Base;
  47.    Log_Inverse_Epsilon_2   : Real'Base;
  48.  
  49.    Complex_Zero : constant Complex := Compose_From_Cartesian (0.0,  0.0);
  50.    Complex_One  : constant Complex := Compose_From_Cartesian (1.0,  0.0);
  51.    Complex_I    : constant Complex := Compose_From_Cartesian (0.0,  1.0);
  52.    HALF_PI      : constant Complex := Compose_From_Cartesian (PI_2, 0.0);
  53.  
  54.    ----------
  55.    -- Sqrt --
  56.    ----------
  57.  
  58.    function Sqrt (X : Complex) return Complex is
  59.       Z   : Complex := X; -- remove if definition gets fixed
  60.       R   : Real'Base;
  61.       R_X : Real'Base;
  62.       R_Y : Real'Base;
  63.       XR  : Real'Base := abs Re (Z);
  64.       YR  : Real'Base := abs Im (Z);
  65.       A   : Real'Base;
  66.    begin
  67.  
  68.       if XR > YR then
  69.          A := YR / XR;
  70.          A := A * A;
  71.  
  72.          if A < 32.0 * Square_Root_Epsilon then
  73.  
  74.             if Re (Z) > 0.0 then
  75.                R_X := Sqrt (XR + 0.5  *
  76.                            (0.5 * YR * YR / XR - (YR * YR / XR) * A / 8.0));
  77.                R_Y := Sqrt (0.5 *
  78.                            (0.5 * YR * YR / XR - (YR * YR / XR) * A / 8.0));
  79.             else
  80.                R_X := Sqrt (0.5 *
  81.                            (0.5 * YR * YR / XR - (YR * YR / XR) * A / 8.0));
  82.                R_Y := Sqrt (XR + 0.5 *
  83.                            (0.5 * YR * YR / XR - (YR * YR / XR) * A / 8.0));
  84.             end if;
  85.  
  86.          else
  87.             R  := XR * Sqrt (1.0 + A);
  88.             R_X := Sqrt (0.5 *  (R + Re (Z)));
  89.             R_Y := Sqrt (0.5 *  (R - Re (Z)));
  90.          end if;
  91.  
  92.       else                                      -- YR > XR
  93.          A := XR / YR;
  94.          A := A * A;
  95.  
  96.          if A < 32.0 * Square_Root_Epsilon then -- YR >> XR
  97.             R  := YR + 0.5 * XR * XR / YR - 0.125 *  (XR * XR / YR) * A;
  98.             R_X := Sqrt (0.5 *  (YR + (0.5 * XR * XR / YR + Re (Z))));
  99.             R_Y := Sqrt (0.5 *  (YR + (0.5 * XR * XR / YR - Re (Z))));
  100.          else
  101.             R  := YR * Sqrt (1.0 + A);
  102.             R_X := Sqrt (0.5 *  (R + Re (Z)));
  103.             R_Y := Sqrt (0.5 *  (R - Re (Z)));
  104.          end if;
  105.       end if;
  106.  
  107.       if Im (Z) < 0.0 then                 -- halve angle, Sqrt of magnitude
  108.          R_Y := -R_Y;
  109.       end if;
  110.       return Compose_From_Cartesian (R_X, R_Y);
  111.  
  112.    exception
  113.       when Constraint_Error =>
  114.          R := Modulus (Compose_From_Cartesian (Re (Z / 4.0), Im (Z / 4.0)));
  115.          R_X := 2.0 * Sqrt (0.5 * R + 0.5 * Re (Z / 4.0));
  116.          R_Y := 2.0 * Sqrt (0.5 * R - 0.5 * Re (Z / 4.0));
  117.  
  118.          if Im (Z) < 0.0 then -- halve angle, Sqrt of magnitude
  119.             R_Y := -R_Y;
  120.          end if;
  121.  
  122.          return Compose_From_Cartesian (R_X, R_Y);
  123.    end Sqrt;
  124.  
  125.    ---------
  126.    -- Log --
  127.    ---------
  128.  
  129.    function Log (X : Complex) return Complex is
  130.       Z : Complex := X;
  131.       RE_Z, IM_Z : Real'Base;
  132.    begin
  133.  
  134.       if Re (Z) = 0.0 and then Im (Z) = 0.0 then
  135.          raise Constraint_Error;
  136.  
  137.       elsif abs (1.0 - Re (Z)) < Root_Root_Epsilon and then
  138.                       abs Im (Z) < Root_Root_Epsilon then
  139.          Set_Re (Z, Re (Z) - 1.0);
  140.          return (1.0 - (1.0 / 2.0 -
  141.                        (1.0 / 3.0 - (1.0 / 4.0) * Z) * Z) * Z) * Z;
  142.       end if;
  143.  
  144.       begin
  145.          RE_Z := Log (Modulus (Z));
  146.       exception
  147.          when Constraint_Error =>
  148.             RE_Z := Log (Modulus (Z / 2.0)) - Log_Two;
  149.       end;
  150.  
  151.       IM_Z := Arctan (Im (Z), Re (Z));
  152.  
  153.       if IM_Z > PI then
  154.          IM_Z := IM_Z - 2.0 * PI;
  155.       end if;
  156.  
  157.       return Compose_From_Cartesian (RE_Z, IM_Z);
  158.    end Log;
  159.  
  160.    ---------
  161.    -- Exp --
  162.    ---------
  163.  
  164.    function Exp (X : Complex) return Complex is
  165.       Z : Complex := X;
  166.       EXP_RE_Z : Real'Base := Exp (Re (Z));
  167.    begin
  168.       return Compose_From_Cartesian (EXP_RE_Z * Cos (Im (Z)),
  169.                                      EXP_RE_Z * Sin (Im (Z)));
  170.    end Exp;
  171.  
  172.  
  173.    function Exp (X : Imaginary) return Complex is
  174.       IM_Z : Real'Base := Im (X);
  175.    begin
  176.       return Compose_From_Cartesian (Cos (IM_Z), Sin (IM_Z));
  177.    end Exp;
  178.  
  179.    --------
  180.    -- ** --
  181.    --------
  182.  
  183.    function "**"
  184.      (Left : Complex;
  185.      Right : Complex)
  186.    return Complex is
  187.       Z1 : Complex := Left;
  188.       Z2 : Complex := Right;
  189.    begin
  190.       if Re (Z2) = 0.0 and then Im (Z2) = 0.0 and then
  191.          Re (Z1) = 0.0 and then Im (Z1) = 0.0 then
  192.          raise Argument_Error;
  193.  
  194.       elsif Re (Z1) = 0.0 and then Im (Z1) = 0.0 and then
  195.              Re (Z2) < 0.0 then
  196.          raise Constraint_Error;
  197.  
  198.       elsif Re (Z1) = 0.0 and then Im (Z1) = 0.0 then
  199.          return Z1;
  200.  
  201.       elsif Re (Z2) = 0.0 and then Im (Z2) = 0.0 then
  202.          return 1.0 + Z2;
  203.  
  204.       elsif Re (Z2) = 1.0 and then Im (Z2) = 0.0 then
  205.          return Z1;
  206.  
  207.       else
  208.          return Exp (Z2 * Log (Z1));
  209.       end if;
  210.    end "**";
  211.  
  212.  
  213.    function "**"
  214.      (Left : Real'Base;
  215.       Right : Complex)
  216.    return Complex is
  217.       X : Real'Base := Left;
  218.       Z : Complex := Right;
  219.    begin
  220.       if Re (Z) = 0.0 and then Im (Z) = 0.0 and then
  221.          X = 0.0 then
  222.          raise Argument_Error;
  223.  
  224.       elsif X = 0.0 and then Re (Z) < 0.0 then
  225.          raise Constraint_Error;
  226.  
  227.       elsif X = 0.0 then
  228.          return Compose_From_Cartesian (X, 0.0);
  229.  
  230.       elsif Re (Z) = 0.0 and then Im (Z) = 0.0 then
  231.          return Complex_One;
  232.  
  233.       elsif Re (Z) = 1.0 and then Im (Z) = 0.0 then
  234.          return Compose_From_Cartesian (X, 0.0);
  235.  
  236.       else
  237.          return Exp (Log (X) * Z);
  238.       end if;
  239.    end "**";
  240.  
  241.  
  242.    function "**" (Left : Complex;
  243.                    Right : Real'Base) return Complex is
  244.       Z : Complex := Left;
  245.       Y : Real'Base := Right;
  246.    begin
  247.       if  Y = 0.0 and then
  248.           Re (Z) = 0.0 and then Im (Z) = 0.0 then
  249.          raise Argument_Error;
  250.       elsif Re (Z) = 0.0 and then Im (Z) = 0.0 and then
  251.             Y < 0.0 then
  252.          raise Constraint_Error;
  253.  
  254.       elsif Re (Z) = 0.0 and then Im (Z) = 0.0 then
  255.          return Z;
  256.  
  257.       elsif Y = 0.0 then
  258.          return Complex_One;
  259.  
  260.       elsif Y = 1.0 then
  261.          return Z;
  262.  
  263.       else
  264.          return Exp (Y * Log (Z));
  265.       end if;
  266.    end "**";
  267.  
  268.    ---------
  269.    -- Sin --
  270.    ---------
  271.  
  272.    function Sin (X : Complex) return Complex is
  273.       Z : Complex := X;
  274.    begin
  275.  
  276.       if abs Re (Z) < Square_Root_Epsilon and then
  277.          abs Im (Z) < Square_Root_Epsilon then
  278.          return Z;
  279.       end if;
  280.  
  281.       return Compose_From_Cartesian (Sin (Re (Z)) * Cosh (Im (Z)),
  282.                                      Cos (Re (Z)) * Sinh (Im (Z)));
  283.    end Sin;
  284.  
  285.    ---------
  286.    -- Cos --
  287.    ---------
  288.  
  289.    function Cos (X : Complex) return Complex is
  290.       Z : Complex := X;
  291.    begin
  292.       return Compose_From_Cartesian (Cos (Re (Z)) * Cosh (Im (Z)),
  293.                                    -Sin (Re (Z)) * Sinh (Im (Z)));
  294.    end Cos;
  295.  
  296.    ---------
  297.    -- Tan --
  298.    ---------
  299.  
  300.    function Tan (X : Complex) return Complex is
  301.       Z : Complex := X;
  302.    begin
  303.       if abs Re (Z) < Square_Root_Epsilon and then
  304.          abs Im (Z) < Square_Root_Epsilon then
  305.          return Z;
  306.  
  307.       elsif Im (Z) > Log_Inverse_Epsilon_2 then
  308.          return Complex_I;
  309.  
  310.       elsif Im (Z) < -Log_Inverse_Epsilon_2 then
  311.          return -Complex_I;
  312.       end if;
  313.  
  314.       return Sin (Z) / Cos (Z);
  315.    end Tan;
  316.  
  317.  
  318.    ---------
  319.    -- Cot --
  320.    ---------
  321.  
  322.    function Cot (X : Complex) return Complex is
  323.       Z : Complex := X;
  324.    begin
  325.       if abs Re (Z) < Square_Root_Epsilon and then
  326.          abs Im (Z) < Square_Root_Epsilon then
  327.          return Complex_One  /  Z;
  328.  
  329.       elsif Im (Z) > Log_Inverse_Epsilon_2 then
  330.          return -Complex_I;
  331.  
  332.       elsif Im (Z) < -Log_Inverse_Epsilon_2 then
  333.          return Complex_I;
  334.       end if;
  335.  
  336.       return Cos (Z) / Sin (Z);
  337.    end Cot;
  338.  
  339.    ------------
  340.    -- Arcsin --
  341.    ------------
  342.  
  343.    function Arcsin (X : Complex) return Complex is
  344.       Z : Complex := X;
  345.       ZA : Complex := Z;
  346.       Result : Complex;
  347.    begin
  348.       if abs Re (Z) < Square_Root_Epsilon and then
  349.          abs Im (Z) < Square_Root_Epsilon then
  350.          return Z;
  351.  
  352.       elsif abs Re (Z) > Inv_Square_Root_Epsilon or
  353.             abs Im (Z) > Inv_Square_Root_Epsilon then
  354.          Result := -Complex_I * (Log (Complex_I * Z) + Log (2.0 * Complex_I));
  355.  
  356.          if Im (Result) > PI_2 then
  357.             Set_Im (Result, PI - Im (Z));
  358.          elsif Im (Result) < -PI_2 then
  359.             Set_Im (Result, -(PI + Im (Z)));
  360.          end if;
  361.       end if;
  362.  
  363.       Result := -Complex_I * Log (Complex_I * Z + Sqrt (1.0 - Z * Z));
  364.  
  365.       if Re (Z) = 0.0 then
  366.          Set_Re (Result, Re (Z));
  367.       elsif Im (Z) = 0.0 then
  368.          Set_Im (Result, Im (Z));
  369.       end if;
  370.  
  371.       return Result;
  372.    end Arcsin;
  373.  
  374.    ------------
  375.    -- Arccos --
  376.    ------------
  377.  
  378.    function Arccos (X : Complex) return Complex is
  379.       Z : Complex := X;
  380.       Result : Complex;
  381.    begin
  382.       if abs Re (Z) < Square_Root_Epsilon and then
  383.          abs Im (Z) < Square_Root_Epsilon then
  384.          return HALF_PI - Z;
  385.  
  386.       elsif abs Re (Z) > Inv_Square_Root_Epsilon or
  387.             abs Im (Z) > Inv_Square_Root_Epsilon then
  388.          return -2.0 * Complex_I * Log (Sqrt ((1.0 + Z) / 2.0) +
  389.                             Complex_I * Sqrt ((1.0 - Z) / 2.0));
  390.       end if;
  391.  
  392.       Result := -Complex_I * Log (Z + Complex_I * Sqrt (1.0 - Z * Z));
  393.  
  394.       if Im (Z) = 0.0 then
  395.          Set_Im (Result, Im (Z));
  396.       end if;
  397.  
  398.       return Result;
  399.    end Arccos;
  400.  
  401.  
  402.    ------------
  403.    -- Arctan --
  404.    ------------
  405.  
  406.    function Arctan (X : Complex) return Complex is
  407.       Z : Complex := X;
  408.    begin
  409.  
  410.       if abs Re (Z) < Square_Root_Epsilon and then
  411.          abs Im (Z) < Square_Root_Epsilon then
  412.          return Z;
  413.       end if;
  414.  
  415.       return -Complex_I * (Log (1.0 + Complex_I * Z)
  416.                          - Log (1.0 - Complex_I * Z)) / 2.0;
  417.    end Arctan;
  418.  
  419.  
  420.    ------------
  421.    -- Arccot --
  422.    ------------
  423.  
  424.    function Arccot (X : Complex) return Complex is
  425.       Z : Complex := X;
  426.       Zt : Complex;
  427.    begin
  428.  
  429.       if abs Re (Z) < Square_Root_Epsilon and then
  430.          abs Im (Z) < Square_Root_Epsilon then
  431.          return HALF_PI - Z;
  432.  
  433.       elsif abs Re (Z) > 1.0 / Epsilon or
  434.             abs Im (Z) > 1.0 / Epsilon then
  435.          Zt := Complex_One  /  Z;
  436.  
  437.          if Re (Z) < 0.0 then
  438.             Set_Re (Zt, PI - Re (Zt));
  439.             return Zt;
  440.          else
  441.             return Zt;
  442.          end if;
  443.       end if;
  444.  
  445.       Zt := Complex_I * Log ((Z - Complex_I) / (Z + Complex_I)) / 2.0;
  446.  
  447.       if Re (Zt) < 0.0 then
  448.          Zt := PI + Zt;
  449.       end if;
  450.       return Zt;
  451.    end Arccot;
  452.  
  453.    ----------
  454.    -- Sinh --
  455.    ----------
  456.  
  457.    function Sinh (X : Complex) return Complex is
  458.       Z : Complex := X;
  459.    begin
  460.  
  461.       if abs Re (Z) < Square_Root_Epsilon and then
  462.          abs Im (Z) < Square_Root_Epsilon then
  463.          return Z;
  464.       end if;
  465.  
  466.       return Compose_From_Cartesian (Sinh (Re (Z)) * Cos (Im (Z)),
  467.                                      Cosh (Re (Z)) * Sin (Im (Z)));
  468.    end Sinh;
  469.  
  470.    ----------
  471.    -- Cosh --
  472.    ----------
  473.  
  474.    function Cosh (X : Complex) return Complex is
  475.       Z : Complex := X;
  476.    begin
  477.       return Compose_From_Cartesian (Cosh (Re (Z)) * Cos (Im (Z)),
  478.                                      Sinh (Re (Z)) * Sin (Im (Z)));
  479.    end Cosh;
  480.  
  481.    ----------
  482.    -- Tanh --
  483.    ----------
  484.  
  485.    function Tanh (X : Complex) return Complex is
  486.       Z : Complex := X;
  487.    begin
  488.  
  489.       if abs Re (Z) < Square_Root_Epsilon and then
  490.          abs Im (Z) < Square_Root_Epsilon then
  491.          return Z;
  492.  
  493.       elsif Re (Z) > Log_Inverse_Epsilon_2 then
  494.          return Complex_One;
  495.  
  496.       elsif Re (Z) < -Log_Inverse_Epsilon_2 then
  497.          return -Complex_One;
  498.       end if;
  499.  
  500.       return Sinh (Z) / Cosh (Z);
  501.    end Tanh;
  502.  
  503.    ----------
  504.    -- Coth --
  505.    ----------
  506.  
  507.    function Coth (X : Complex) return Complex is
  508.       Z : Complex := X;
  509.    begin
  510.  
  511.       if abs Re (Z) < Square_Root_Epsilon and then
  512.          abs Im (Z) < Square_Root_Epsilon then
  513.          return Complex_One  /  X;
  514.  
  515.       elsif Re (X) > Log_Inverse_Epsilon_2 then
  516.          return Complex_One;
  517.  
  518.       elsif Re (X) < -Log_Inverse_Epsilon_2 then
  519.          return -Complex_One;
  520.       end if;
  521.  
  522.       return Cosh (Z) / Sinh (Z);
  523.    end Coth;
  524.  
  525.    -------------
  526.    -- Arcsinh --
  527.    -------------
  528.  
  529.    function Arcsinh (X : Complex) return Complex is
  530.       Z : Complex := X;
  531.       Result : Complex;
  532.    begin
  533.  
  534.       if abs Re (Z) < Square_Root_Epsilon and then
  535.          abs Im (Z) < Square_Root_Epsilon then
  536.          return Z;
  537.  
  538.       elsif abs Re (Z) > Inv_Square_Root_Epsilon or
  539.             abs Im (Z) > Inv_Square_Root_Epsilon then
  540.  
  541.          Result := Log_Two + Log (Z); -- may have wrong sign
  542.  
  543.          if (Re (Z) < 0.0 and Re (Result) > 0.0)
  544.            or else  (Re (Z) > 0.0 and Re (Result) < 0.0)
  545.          then
  546.             Set_Re  (Result, -Re (Result));
  547.          end if;
  548.  
  549.          return Result;
  550.       end if;
  551.  
  552.       Result := Log (Z + Sqrt (1.0 + Z*Z));
  553.  
  554.       if Re (Z) = 0.0 then
  555.          Set_Re  (Result, Re (Z));
  556.       elsif Im  (Z) = 0.0 then
  557.          Set_Im (Result, Im  (Z));
  558.       end if;
  559.  
  560.       return Result;
  561.    end Arcsinh;
  562.  
  563.    -------------
  564.    -- Arccosh --
  565.    -------------
  566.  
  567.    function Arccosh (X : Complex) return Complex is
  568.       Z : Complex := X;
  569.       Result : Complex;
  570.    begin
  571.  
  572.       if abs Re  (Z) < Square_Root_Epsilon and then
  573.          abs Im (Z) < Square_Root_Epsilon then
  574.          Result := Compose_From_Cartesian (-Im (Z), -PI_2 + Re (Z));
  575.  
  576.       elsif abs Re  (Z) > Inv_Square_Root_Epsilon or
  577.             abs Im (Z) > Inv_Square_Root_Epsilon then
  578.          Result := Log_Two + Log (Z);
  579.  
  580.       else
  581.          Result := 2.0 * Log (Sqrt ((1.0 + Z) / 2.0) +
  582.                               Sqrt ((Z - 1.0) / 2.0));
  583.       end if;
  584.  
  585.       if Re (Result) <= 0.0 then
  586.          Result := -Result;
  587.       end if;
  588.  
  589.       return Result;
  590.    end Arccosh;
  591.  
  592.    -------------
  593.    -- Arctanh --
  594.    -------------
  595.  
  596.    function Arctanh (X : Complex) return Complex is
  597.       Z : Complex := X;
  598.    begin
  599.  
  600.       if abs Re (Z) < Square_Root_Epsilon and then
  601.          abs Im (Z) < Square_Root_Epsilon then
  602.          return Z;
  603.       end if;
  604.  
  605.       return (Log (1.0 + Z) - Log (1.0 - Z)) / 2.0;
  606.    end Arctanh;
  607.  
  608.  
  609.    --------------
  610.    -- Arctcoth --
  611.    --------------
  612.  
  613.    function Arccoth (X : Complex) return Complex is
  614.       Z : Complex := X;
  615.       R : Complex;
  616.    begin
  617.  
  618.       if abs Re (Z) < Square_Root_Epsilon
  619.          and then abs Im (Z) < Square_Root_Epsilon
  620.       then
  621.          return PI_2 * Complex_I + Z;
  622.  
  623.       elsif abs Re (Z) > 1.0 / Epsilon or else
  624.             abs Im (Z) > 1.0 / Epsilon then
  625.          if Im (Z) > 0.0 then
  626.             return Complex_Zero;
  627.          else
  628.             return PI * Complex_I;
  629.          end if;
  630.  
  631.       elsif Im (Z) = 0.0 and then Re (Z) = 1.0 then
  632.          raise Constraint_Error;
  633.  
  634.       elsif Im (Z) = 0.0 and then Re (Z) = -1.0 then
  635.          raise Constraint_Error;
  636.       end if;
  637.  
  638.       begin
  639.          R := Log ((1.0 + Z) / (Z - 1.0)) / 2.0;
  640.       exception
  641.          when Constraint_Error =>
  642.             R := (Log (1.0 + Z) - Log (Z - 1.0)) / 2.0;
  643.       end;
  644.  
  645.       if Im (R) < 0.0 then
  646.          Set_Im (R, PI + Im (R));
  647.       end if;
  648.  
  649.       if Re (Z) = 0.0 then
  650.          Set_Re (R, Re (Z));
  651.       end if;
  652.  
  653.       return R;
  654.    end Arccoth;
  655.  
  656. begin                                 -- initialize needed pseudo-constants
  657.    Epsilon := Real (Real'Model_Epsilon);
  658.  
  659.    while Epsilon / Real (Real'Machine_Radix) + 1.0 /= 1.0 loop
  660.       Epsilon := Epsilon / Real (Real'Machine_Radix);
  661.    end loop;
  662.  
  663.    Square_Root_Epsilon     := Sqrt (Epsilon);
  664.    Inv_Square_Root_Epsilon := 1.0 / Square_Root_Epsilon;
  665.    Root_Root_Epsilon       := Sqrt (Square_Root_Epsilon);
  666.    Log_Inverse_Epsilon_2   := Log (1.0 / Epsilon) / 2.0;
  667.  
  668. end Ada.Numerics.Generic_Complex_Elementary_Functions;
  669.